#!/usr/bin/env python

import time
import robot_gesture

HUMAN_SIGNALS_FNAME = 'human-signals.txt'


class Arrousal(object):
    Neutral, High, Low = range(3)

class Personality(object):
    Introverted, Extroverted = range(2)

class Difficulty(object):
    Easy, Difficult = range(2)

class EmotionalState(object):
    Frustrated, Relaxed = range(2)

class Behavior(object):
    Empathic, Ignorant, EncourageBased = range(3)


HUMAN_PERSONALITY = Personality.Extroverted
HUMAN_TASK_DIFFICULTY = Difficulty.Easy

def sleep(sec):
    #print "sleep" + str(sec)
    #time.sleep(sec)
    pass

def arrousal_from_str(str_arrousal):
    if str_arrousal == 'neutral':
        return Arrousal.Neutral
    elif str_arrousal == 'high':
        return Arrousal.High
    elif str_arrousal == 'low':
        return Arrousal.Low
    else:
        raise Exception('Unrecognised arrousal type ' + str_arrousal)


def get_emo_state(difficulty, arrousal):
    """
    [diff/arrousal]  Low       Neutral     High
     Easy            Relaxed   Frustrated  Frustrated
     Difficult       Relaxed   Relaxed     Frustrated
    """
    if difficulty == Difficulty.Easy:
        if arrousal == Arrousal.Low:
            return EmotionalState.Relaxed
        return EmotionalState.Frustrated
    # difficulty == Difficulty.Difficult
    if arrousal == Arrousal.High:
        return EmotionalState.Frustrated
    return EmotionalState.Relaxed


def get_behavior(personality, emotional_state):
    """
    [pers/emo]    Frustrated   Relaxed
    Introverted   Empathic     Ignorant
    Extroverted   Ignorant     EncourageBased
    """
    if personality == Personality.Introverted and emotional_state == EmotionalState.Frustrated:
        return Behavior.Empathic
    if personality == Personality.Extroverted and emotional_state == EmotionalState.Relaxed:
        return Behavior.EncourageBased
    return Behavior.Ignorant



class HumanSignals(object):
    """Read preprocessed human phisyological signals (only arrousal
    for now)."""
    def __init__(self):
        self.f = None
        self.f = open(HUMAN_SIGNALS_FNAME)

    def __del__(self):
        if self.f is not None:
            self.f.close()

    def next_feeling(self):
        line = self.f.readline().strip()
        if len(line) == 0:
            return  None
        [delay_str, arrousal] = line.split(' ')
        delay = int(delay_str)

        # wait until this set of human signals is recorded
        # this is simulated by the delay field in the file.
        sleep(delay)
        return arrousal_from_str(arrousal)



tries_before_speed_reduction = 3
tries_before_speed_increase  = 3
robot_speed = 0.5
def action_empathy():
    global robot_speed
    global tries_before_speed_reduction
    global tries_before_speed_increase
    print "<empathy>"
    robot_gesture.calm_down()
    sleep(2)
    
    tries_before_speed_increase = 3
    tries_before_speed_reduction = tries_before_speed_reduction - 1
    if tries_before_speed_reduction == 0:
        robot_speed = 0.7 * robot_speed
        tries_before_speed_reduction = 3
        robot_gesture.back_up()

    robot_gesture.pickup(robot_speed)
    robot_gesture.pickup(robot_speed)
    print "</empathy>"

def action_ignore():
    global robot_speed
    global tries_before_speed_reduction
    global tries_before_speed_increase
    print "<ignore>"
    robot_gesture.pickup(robot_speed)
    robot_gesture.pickup(robot_speed)
    robot_gesture.pickup(robot_speed)
    tries_before_speed_reduction = 3
    tries_before_speed_increase = tries_before_speed_increase - 1
    if tries_before_speed_increase == 0:
        robot_speed = robot_speed / 0.7
        tries_before_speed_increase = 3
    print "</ignore>"
    
def action_encourage():
    global robot_speed
    global tries_before_speed_reduction
    global tries_before_speed_increase
    print "<empathy>"
    robot_gesture.headApproval()
    robot_gesture.davai()
    robot_gesture.davai()
    robot_gesture.davai()
    robot_gesture.applause()
    robot_gesture.pickup(robot_speed)
    tries_before_speed_reduction = 3
    tries_before_speed_increase = tries_before_speed_increase - 1
    if tries_before_speed_increase == 0:
        robot_speed = 1.1 * robot_speed
        tries_before_speed_increase = 3
    print "</empathy>"
    

def feeling_to_action(personality, difficulty, arrousal):
    behavior = get_behavior(personality, get_emo_state(difficulty, arrousal))
    if behavior == Behavior.Empathic:
        action_empathy()
    elif behavior == Behavior.Ignorant:
        action_ignore()
    else:
        action_encourage()



def main():
    personality = HUMAN_PERSONALITY
    difficulty  = HUMAN_TASK_DIFFICULTY

    h = HumanSignals()
    #robot_gesture.salut()
    while True:
        arrousal = h.next_feeling()
        if arrousal is None:
            break
        feeling_to_action(personality, difficulty, arrousal)

if __name__ == "__main__":
    main()
